#include "CommandBatch.hpp"

using namespace BFT::messages;

CommandBatch::CommandBatch(boost::shared_ptr<std::vector<boost::shared_ptr<Entry> > > _entries, uint16_t _entryCount)
{
	entries=_entries;
	entryCount=_entryCount;
	if(entries.get()->size()!=entryCount)
	{
		fprintf(stderr, "CommandBatch constructor says: something wrong is happening there...\n");
		exit(181);
	}
	bytes_size=0;
}

CommandBatch::CommandBatch(boost::shared_ptr<std::vector<boost::shared_ptr<Entry> > > _entries)
{
	entries=_entries;
	entryCount=_entries.get()->size();
	bytes_size=0;
}

CommandBatch::CommandBatch(boost::shared_ptr<char> _bytes, int _bytes_size, uint16_t _entryCount)
{
	entryCount=_entryCount;
	entries = Entry::getList(_bytes, _bytes_size, entryCount);
	bytes_size=0;
}


boost::shared_ptr<char> CommandBatch::getBytes(int & _bytes_size)
{
	
	if (bytes_size == 0)
	{
		for (unsigned int i=0; i < entryCount; i++)
		{
			if (entries.get()->at(i).use_count() != 0)
			{
				bytes_size += entries.get()->at(i).get()->getSize();
			}
			else
			{
				fprintf(stderr, "CommandBatch::getBytes says: something wrong is happening there...\n");
				exit(180);
			}
		}
		
		bytes.reset((char*)malloc(sizeof(char)*bytes_size), free);
		
		int offset=0;
		int size=0;
		boost::shared_ptr<char> temp_entry;		
		for (unsigned int i=0; i < entryCount; i++)
		{
			//temp_entry.reset();
			temp_entry = entries.get()->at(i).get()->getBytes(size);
			/*
			fprintf(stderr," - - - temp_entry information - - - \n");
			entries.get()[i].get()->printInfo();
			*/
			memcpy( (void*)(bytes.get()+offset), (const void*)temp_entry.get(), size );
			offset += size; 
		}
		
		if(offset != bytes_size)
		{
			fprintf(stderr, "CommandBatch::getBytes says: offset != bytes_size...\n");
			exit(182);	
		}
		
	}
	
	_bytes_size = bytes_size;
	return bytes;
}

bool CommandBatch::equals(boost::shared_ptr<CommandBatch> _batch)
{
	bool equal = ( entryCount == _batch.get()->getEntryCount());
	
	for (unsigned int i = 0; i < entryCount && equal; i++)
		equal = equal && entries.get()->at(i).get()->equals( _batch.get()->getEntries().get()->at(i));
	
	return equal;
}

void CommandBatch::printInfo()
{
	fprintf(stdout,"CommandBatch information:\n");
	fprintf(stdout,"entryCount : %d\n",entryCount);
	for (int i=0; i<entryCount;i++)
	{
		fprintf(stdout,"entry at index %d:\n",i);
		entries.get()->at(i).get()->printInfo();
	}
	fprintf(stdout,"no more entries in this CommandBatch\n");
}

int CommandBatch::getSize() 
{
	if(bytes_size==0)	
	{
		int temp;
		getBytes(temp);
	}
	return bytes_size;
}
